package com.yangye.springclouddemozookeeper.listener;

import com.yangye.springclouddemozookeeper.utils.ZKUtils;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Properties;

/**
 * @author yangye
 * @date 2020/10/19
 */
@Component
public class ServiceRegisterListener implements ApplicationListener<ContextRefreshedEvent> {

	private static final String BASE_PATH = "/service";

	private ZooKeeper zk;

	public void register(String address, int port) {

		try {
			zk = ZKUtils.getZK(new DefaultWatcher());
			Stat exists = zk.exists(BASE_PATH, false);
			if (Objects.isNull(exists)) {
				// 初始化父节点
				zk.create(BASE_PATH, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
			}
			String serviceInfo = address + ":" + port;
			zk.create(BASE_PATH + "/child", serviceInfo.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
			System.out.println("服务注册成功");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void updateServerList() {
		List<String> list = new ArrayList<>();
		try {
			List<String> children = zk.getChildren(BASE_PATH, true);
			for (String child : children) {
				byte[] data = zk.getData(BASE_PATH + "/" + child, false, null);
				String host = new String(data, "utf-8");
				list.add(host);
			}
			DefaultLoadBanlancer.SERVER_LIST = list;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
		Properties properties = new Properties();

		try {
			properties.load(ServiceRegisterListener.class.getClassLoader().getResourceAsStream("application.properties"));
			String host = InetAddress.getLocalHost().getHostAddress();
			int port = Integer.parseInt(properties.getProperty("server.port"));

			register(host, port);

			updateServerList();

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	class DefaultWatcher implements Watcher {
		@Override
		public void process(WatchedEvent watchedEvent) {
			// 监听注册节点变化
			if (watchedEvent.getType() == Event.EventType.NodeChildrenChanged && watchedEvent.getPath().equals(BASE_PATH)) {
				System.out.println("注册节点变化");
				updateServerList();
			}
		}
	}
}
